infra: scale anyplot-app to zero - #10812
Conversation
The frontend service held a permanently warm Cloud Run instance for ~EUR 8.30/month while 99.56 % of the billed time was idle. It is a static nginx image whose cold start is ~0.26 s (p50 258 ms), so the warm instance bought almost nothing. A 7-day request trace at one-minute resolution shows the service is busy in 60 % of all minutes and the longest gap between requests is 11 minutes, against Cloud Run's ~15 minute idle window. The instance is therefore reclaimed rarely if ever, and time to first byte for visitors and crawlers stays where it is. anyplot-api deliberately keeps min-instances=1: its cold start is ~11.6 s and its traffic does leave gaps beyond 15 minutes. The live service was updated in the same breath; this pins the value so the next deploy does not restore it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011qccek5dba72zaizDBGK61
There was a problem hiding this comment.
🟡 Changes recommended
The new changelog entry is missing the required PR reference suffix and there are a couple of small but concrete maintainability/formatting issues to address.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR updates the frontend Cloud Run deployment configuration so anyplot-app can scale to zero (reducing idle cost) and adds a corresponding changelog entry documenting the change and rationale.
Changes:
- Set
anyplot-appCloud Run--min-instancesfrom1to0in the frontend Cloud Build deploy step. - Add an
[Unreleased]changelog entry describing the operational change and motivation.
File summaries
| File | Description |
|---|---|
| CHANGELOG.md | Adds an Unreleased entry documenting that anyplot-app now scales to zero. |
| app/cloudbuild.yaml | Updates the Cloud Run deploy args to use --min-instances 0 (and documents the rationale inline). |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Copilot review on #10812: - percent style: the file writes "28%", not "28 %" - the header requires a PR reference on every [Unreleased] bullet - the inline cloudbuild comment carried a 7-day traffic trace and a euro figure that will go stale; keep the durable reasoning there and leave the measurements in the PR Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011qccek5dba72zaizDBGK61
There was a problem hiding this comment.
🟢 Approval recommended
Only a minor changelog grammar nit was found; the functional Cloud Build change is straightforward and consistent with the stated intent.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
Compound adjective, consistent with "one-minute resolution" in the same bullet. Copilot review on #10812. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011qccek5dba72zaizDBGK61
There was a problem hiding this comment.
🔵 Needs a closer look
It changes production deployment/scaling behavior for a Cloud Run service, which warrants final human verification of operational impact despite the small diff.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 0 new
- Review effort level: Lite
What
anyplot-appmoves frommin-instances=1to0, pinned inapp/cloudbuild.yaml. The live service was already updated in the same breath (revisionanyplot-app-00150-28q), so this commit stops the next deploy from restoring the old value.anyplot-apideliberately keepsmin-instances=1— see below.Why
Came out of a cost audit across the three GCP projects. The frontend service held a permanently warm Cloud Run instance while doing almost nothing with it:
The warm instance bought back roughly 260 seconds of aggregate wait across an entire month, behind Cloudflare, on a service that boots in a quarter of a second.
Why this is safe
The question is whether the service would actually go cold. A 7-day request trace at one-minute resolution says no:
Cloud Run reclaims an idle instance after roughly 15 minutes. Over a full week,
anyplot-appnever had a gap that long, so in practice the instance stays resident and time to first byte for visitors and crawlers is unchanged. Post-change spot checks onhttps://anyplot.ai/returned HTTP 200 at 95–196 ms TTFB.This is an expectation, not a guarantee — the idle window is not a documented SLA. A follow-up check is scheduled for 2026-09-06 against the before-values above (startup latencies, request latencies, billable instance time, plus Search Console crawl response time). Rollback is one flag.
anyplot-apikeeps its warm instance because both halves of the argument invert there: its cold start is ~11.6 s, and its traffic does leave gaps beyond 15 minutes.Test plan
app/cloudbuild.yamlparses and the deploy step carries--min-instances '0',--max-instances '3',--memory '512Mi'minScaleannotation absent, traffic 100 % on the new revisionhttps://anyplot.ai/returns HTTP 200🤖 Generated with Claude Code
https://claude.ai/code/session_011qccek5dba72zaizDBGK61